package geppetto.cat.programs;


import geppetto.cat.alignments.Alignment;
import geppetto.cat.alignments.AlignmentsSet;
import geppetto.cat.alignments.output.AlignerOutputLatex;
import geppetto.cat.common.StaticTools;
import geppetto.cat.corpus.BilingualCorpus;
import geppetto.cat.models.AbstractModel;
import geppetto.cat.models.AgreementHMM;
import geppetto.cat.models.HMM;
import geppetto.phraseHMM.BijectiveHMM;
import geppetto.phraseHMM.RegularHMM;
import geppetto.phraseHMM.SymmetricHMM;

import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;




public class PrintPosteriors {
	String corpusDescription;

	int size, maxSentenceSize;

	String forwardModelDir;
	String backwardModelDir;

	String modelName;
	String baseDir;

	AbstractModel mhmm, mhmmb;

	BilingualCorpus forwardCorpus, backwardCorpus;

	double  epsilon;
	double  slack;
	int maxStep;
	int  maxProjection;
	

	public PrintPosteriors(String[] args) {
		corpusDescription = args[0];
		size = Integer.parseInt(args[1]);
		maxSentenceSize = Integer.parseInt(args[2]);
		forwardModelDir = args[3];
		backwardModelDir = args[4];
		modelName = args[5];
		baseDir = args[6];
		epsilon = Double.parseDouble(args[7]);
		slack = Double.parseDouble(args[8]);
		maxStep = Integer.parseInt(args[9]);
		maxProjection = Integer.parseInt(args[10]);
		
		System.out.println("Corpus " + corpusDescription);
		System.out.println("Size " + size);
		System.out.println("ModelDir forward" + forwardModelDir);
		System.out.println("ModelDir backward" + backwardModelDir);
		System.out.println("Model Name " + modelName);
		System.out.println("---");
		
	}



	public void run() throws IOException {
		BilingualCorpus[] corpus = GenericMethods.initializeCorpus(corpusDescription, size, maxSentenceSize);
	

		
		AbstractModel[] models= GenericMethods.initializeModelsFullDir(corpus[0], corpus[1], 
				modelName, 
				forwardModelDir,backwardModelDir, 
				epsilon, slack, maxStep, maxProjection);
		//Decode to get original Posteriors
		AlignmentsSet originalPostForward = models[0].viterbiAlignments(BilingualCorpus.TEST_CORPUS, false);
		AlignmentsSet originalPostBackward = models[1].viterbiAlignments(BilingualCorpus.TEST_CORPUS, false);
		
		
		//Create a new Bijective out of the old model Parameteres
		BijectiveHMM bhmmf = new BijectiveHMM(corpus[0],((RegularHMM)models[0])._tb,((RegularHMM)models[0])._distortion,
				0,epsilon,slack,maxSentenceSize,maxProjection);
		BijectiveHMM bhmmb = new BijectiveHMM(corpus[1],((RegularHMM)models[1])._tb,((RegularHMM)models[1])._distortion,
				0,epsilon,slack,maxSentenceSize,maxProjection);
		System.out.println("Starting bijective projections");
		AlignmentsSet bijectivePostForward = bhmmf.viterbiAlignments(BilingualCorpus.TEST_CORPUS, true);
		AlignmentsSet bijectivePostBackward = bhmmb.viterbiAlignments(BilingualCorpus.TEST_CORPUS, true);

		//Create a new symmetric out of old parameters
		SymmetricHMM symmHMM = new SymmetricHMM(corpus[0],corpus[1],((RegularHMM)models[0])._tb,((RegularHMM)models[1])._tb,
				((RegularHMM)models[0])._distortion,((RegularHMM)models[1])._distortion,0,
				epsilon,slack,maxSentenceSize,maxProjection);
		SymmetricHMM symmHMMB = ((SymmetricHMM) symmHMM).getBackwardModel(); 
		System.out.println("Starting symmetric projections");
		AlignmentsSet symmetricPostForward = symmHMM.viterbiAlignments(BilingualCorpus.TEST_CORPUS, true);
		AlignmentsSet symmetricsPostBackward = symmHMMB.viterbiAlignments(BilingualCorpus.TEST_CORPUS, true);
	
		StaticTools.createDir(baseDir);
		PrintStream bothPrinter = new PrintStream(baseDir+ "/"+corpus[0].getName()+"-"+size+"-"+"posteriors-"+slack+"-"+epsilon+".tex");
		AlignerOutputLatex.printBegin(bothPrinter);
		
		for(int i = 0; i < corpus[0].getGold().size(); i++){
			Alignment gold = corpus[0].getGold().get(i);
			if(gold._foreignLen < 15 && gold._sourceLen < 15){
				printPosteriors(originalPostForward.get(i), originalPostBackward.get(i),
						bijectivePostForward.get(i),bijectivePostBackward.get(i),
						symmetricPostForward.get(i),symmetricsPostBackward.get(i),
						gold, 
						corpus[0], bothPrinter, "");
			}
		}
		AlignerOutputLatex.printEnd(bothPrinter);
		
	}
	
	
	public  void printPosteriors(
			Alignment forwardNormal, Alignment backwardNormal, 
			Alignment forwardBijective, Alignment backwardBijective, 
			Alignment forwardSymmetric, Alignment backwardSymmetric, 
			Alignment gold,
			BilingualCorpus corpus, PrintStream out, String caption)
			throws UnsupportedEncodingException {
		int sentenceNumber = forwardNormal.getSentenceNumber();
		byte sourceSentence = forwardNormal.getSentenceSource();
		// out.println("Gold Alignment for Sentence " +
		// alignment._sentenceNumber);
		int foreignSize = forwardNormal.getForeignLenght();
		int sourceSize = forwardNormal.getSourceLenght();
		AlignerOutputLatex.printBeginTable(out, foreignSize * 2 + 3);
		// Line with number

		AlignerOutputLatex.printLineWithNumber(out, foreignSize);
		AlignerOutputLatex.printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		// Print each entry
		for (int si = 0; si < sourceSize; si++) {
			AlignerOutputLatex.printEntriePost(out, si, foreignSize, forwardNormal, gold, corpus,
					sentenceNumber, sourceSentence);
			AlignerOutputLatex.printBackwardEntriePost(out, si, foreignSize, backwardNormal, gold, corpus,
					sentenceNumber, sourceSentence);
			out.println("\\alsw{"
					+ AlignerOutputLatex.outputLatexString(corpus.getSourceWord(sentenceNumber,
							sourceSentence, si)) + "}\\\\");
		}
		AlignerOutputLatex.printLineWithNumber(out, foreignSize);
		AlignerOutputLatex.printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		// Print each entry
		for (int si = 0; si < sourceSize; si++) {
			AlignerOutputLatex.printEntriePost(out, si, foreignSize, forwardBijective,forwardNormal, gold, corpus,
					sentenceNumber, sourceSentence);
			AlignerOutputLatex.printBackwardEntriePost(out, si, foreignSize, backwardBijective,backwardNormal, gold, corpus,
					sentenceNumber, sourceSentence);
			out.println("\\alsw{"
					+ AlignerOutputLatex.outputLatexString(corpus.getSourceWord(sentenceNumber,
							sourceSentence, si)) + "}\\\\");
		}
		AlignerOutputLatex.printLineWithNumber(out, foreignSize);
		AlignerOutputLatex.printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		// Print each entry
		for (int si = 0; si < sourceSize; si++) {
			AlignerOutputLatex.printEntriePost(out, si, foreignSize, forwardSymmetric,forwardNormal, gold, corpus,
					sentenceNumber, sourceSentence);
			AlignerOutputLatex.printBackwardEntriePost(out, si, foreignSize, backwardSymmetric,backwardNormal, gold, corpus,
					sentenceNumber, sourceSentence);
			out.println("\\alsw{"
					+ AlignerOutputLatex.outputLatexString(corpus.getSourceWord(sentenceNumber,
							sourceSentence, si)) + "}\\\\");
		}
		
		AlignerOutputLatex.printBottomLine(out, foreignSize, sentenceNumber, sourceSentence,
				corpus);
		AlignerOutputLatex.printBottomLine(out, foreignSize, sentenceNumber, sourceSentence,
				corpus);
		out.println(" \\\\");
		AlignerOutputLatex.printEndTable(out, caption);
		out.println("\\clearpage\\pagebreak");
	}


	public static void main(String[] args) throws IOException {
		PrintPosteriors exp = new PrintPosteriors(args);
		exp.run();
	}

}
